home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacFormat 1995 May
/
macformat-024.iso
/
Shareware City
/
Developers
/
TransSkel Pascal 2.5
/
TransDisplay
/
TransDisplay.p
< prev
next >
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
NeXTSTEP
RISC OS/Acorn
UTF-8
Wrap
Text File
|
1994-12-14
|
28.1 KB
|
1,096 lines
|
[
TEXT/PJMM
]
{ TransDisplay version 1.0 - TransSkel plug-in module supporting}
{ an arbitrary number of generic display windows with memory.}
{ TransSkel and TransDisplay are public domain, and are written by:}
{ Paul DuBois}
{ Wisconsin Regional Primate Research Center}
{ 1220 Capital Court}
{ Madison WI 53706 USA}
{ UUCP: [allegra,ihnp4,seismo]!uwvax !uwmacc !dubois }
{ ARPA : dubois @ unix.macc.wisc.edu }
{ dubois @ rhesus.primate.wisc.edu }
{ The Pascal Version of TransSkel is public domain and was ported by }
{ Owen Hartnett }
{ Ωhm Software }
{ 163 Richard Drive }
{ Tiverton, RI 02878 }
{ CSNET: omh@cs.brown.edu.CSNET }
{ ARPA: omh%cs.brown.edu@relay.cs.net-relay.ARPA }
{ UUCP: [ihnp4,allegra]!brunix !omh }
{ Psychic Wavelength: 182.2245 Meters (sorry, couldn't resist) }
{ This version of TransDisplay written for Lightspeed Pascal. Lightspeed Pascal}
{ is a trademark of:}
{ THINK Technologies, Inc}
{ 420 Bedford Street Suite 350}
{ Lexington, MA 02173 USA}
{ History}
{ 08/25/86 Genesis. Beta version.}
{ 09/15/86 Changed to allow arbitrary number of windows. Changed}
{ version number to 1.0.}
{ 01/10/87 Ported to LightSpeed Pascal by Owen Hartnett }
{ Ωhm Software, 163 Richard Drive, Tiverton, RI 02878 }
{ 12/2/88 Made changes to add conditional compiling if you only need }
{ one TransDisplay window. Set the following cond variable }
{ singleDisplay to true if you want only one TransDisplay window }
{ and want smaller code size. Made adjustments for LSP 2.0 }
{dec -94: Two seriou bugs fixed by Ingemar R, both causing problems with multiple TransDisplay windows:}
{– Mouse events could be sent to the wrong display window.}
{– SyncGlobals didn't check dispInfo for nil, which could cause crashes.}
unit TransDisplay;
interface
{$SETC singleDisplay:=false }
uses
{$IFC UNDEFINED THINK_PASCAL}
Memtypes, Quickdraw, OSIntf, ToolIntf, PackIntf,
{$ENDC}
TransSkel;
procedure SetDWindow (theWind: WindowPtr);
procedure DisplayString (theStr: str255);
procedure DisplayHexLong (l: longint);
procedure DisplayHexInt (i: integer);
procedure DisplayHexChar (c: char);
procedure DisplayBoolean (b: Boolean);
procedure DisplayChar (c: char);
procedure DisplayInt (i: integer);
procedure DisplayLong (l: longint);
procedure DisplayLn;
procedure DisplayText (theText: Ptr; len: longint);
function GetNewDWindow (resourceNum: integer; behind: WindowPtr): WindowPtr;
function NewDWindow (bounds: Rect; title: Str255; visible: Boolean; behind: WindowPtr; goAway: Boolean; refcon: longint): WindowPTr;
procedure FlushDWindow (theWind: WindowPtr; byteCount: longint);
procedure GetDWindow (var theWind: WindowPtr);
procedure SetDWindowFlush (theWind: WindowPtr; maxText, flushAmt: longint);
procedure SetDWindowNotify (theWind: WindowPTr; p: ProcPtr);
procedure SetDWindowPos (theWind: WindowPtr; lineNum: integer);
procedure SetDWindowStyle (theWind: WindowPtr; font, size, wrap, just: integer);
function GetDWindowTE (theWind: WindowPtr): TEHandle;
function IsDWindow (theWind: WindowPtr): Boolean;
procedure TransDisplayInit;
implementation
{ Display window types, constants, variables.}
const
monaco = 4;
{$IFC not singleDisplay }
type
DIPtr = ^DisplayInfo;
DIHandle = ^DIPtr;
DisplayInfo = record
dWind: WindowPtr; { display window }
dTE: TEHandle; { window text }
dScroll: ControlHandle; { window scroll bar }
dActivate: ProcPtr; { notification procedure }
dMaxText: longint; { max text length }
dFlushAmt: longint; { amount to autoflush }
dNext: DIHandle; { next window structure }
end;
{$ENDC}
var
{ Look at TransDisplayInit procedure for initial values of these variables }
d_font, d_size: integer; { default font }
{ default pointsize }
d_wrap, d_just: integer; { default word wrap (on) }
{ default justification }
d_maxText, d_flushAmt: longint; { default max text allowed }
{ default autoflush amount }
d_activate: ProcPtr; { default notification proc }
{ Lowest allowable values for autoflush characteristics}
d_loMaxText, d_loFlushAmt: longint;
{$IFC not singleDisplay }
dwList: DIHandle;
{ Variables pertaining to the display window being operated on}
{ (updated, resized, etc.). This window is not necessarily the}
{ same as curDispWind! These variables are synced to the window}
{ with SyncGlobals. }
dispInfo: DIHandle; { info structure }
{$ENDC}
dispWind: WindowPtr; { the window }
dispTE: TEHandle; { window text }
dispScroll: ControlHandle; { the scroll bar }
dActivate: ProcPtr; { notification procedure }
dMaxText, dFlushAmt: longint; { max text allowed }
{ amount to flush }
{ curDispWind is the current output window.}
{ If curDispWind = nil, output is turned off.}
curDispWind: WindowPtr;
{ -------------------------------------------------------------------- }
{ Miscellaneous Internal (private) Routines }
{ -------------------------------------------------------------------- }
{ Draw grow box of dispWind in lower right hand corner}
procedure DrawGrowBox;
var
oldClip: RgnHandle;
r: Rect;
begin
r := dispWind^.portRect;
r.left := r.right - 15; { draw only in corner }
r.top := r.bottom - 15;
oldClip := NewRgn;
GetClip(oldClip);
ClipRect(r);
DrawGrowIcon(dispWind);
SetClip(oldClip);
DisposeRgn(oldClip);
end;
{ -------------------------------------------------------------------- }
{ Lowest-level Internal (Private) Display Window Routines }
{ -------------------------------------------------------------------- }
{$IFC not singleDisplay}
{ Get display window info associated with window.}
{ Return nil if window isn't a known display window.}
function GetDInfo (theWind: WindowPtr): DIHandle;
var
h: DIHandle;
foundit: Boolean;
begin
h := dwList;
foundit := false;
while (h <> nil) and not foundit do
begin
if h^^.dWind = theWind then
begin
GetDInfo := h;
h := nil;
foundit := true;
end
else
h := h^^.dNext;
end;
if not foundit then
GetDInfo := nil; {make it a nop }
end;
{$ENDC}
{$IFC singleDisplay}
procedure SyncGlobals (theWind: WindowPtr);
begin
end; { make it a nop }
{$ELSEC }
{ Synchronize globals to a display window. theWind must be a legal}
{ display window, with one exception: if theWind is nil, the}
{ variables are synced to the current port. That is safe (and}
{ correct) because:}
{ (i) nil is only passed by display window handler procedures,}
{ which are only called by TransSkel for display window}
{ events.}
{ (ii) TransSkel always sets the port to the window before}
{ calling the handler proc. <- NO LONGER TRUE!}
{ Hence, use of the current port under these circumstances}
{ always produces a legal display window.}
{ SyncGlobals is not used in single display mode, because the}
{ globals are all set by SetupDWindow and do not change thereafter.}
procedure SyncGlobals (theWind: WindowPtr);
var
dp: DIPtr;
begin
if theWind = nil then { use current window }
GetPort(theWind);
dispWind := theWind;
dispInfo := GetDInfo(dispWind);
{Bugfix by Ingemar 941208: The current port might not be a display window!}
if dispInfo <> nil then
begin
dp := dispInfo^;
dispScroll := dp^.dScroll;
dispTE := dp^.dTE;
dActivate := dp^.dActivate;
dMaxText := dp^.dMaxText;
dFlushAmt := dp^.dFlushAmt;
end;
end;
{$ENDC}
{ Calculate the dimensions of the editing rectangle for}
{ dispWind (which must be set properly and is assumed to }
{ the current port). (The viewRect and destRect are the}
{ same size .) Assumes the port , text font and text size are all}
{ set properly. The viewRect is sized so that an integral}
{ number of lines can be displayed in it, i.e., so that a}
{ partial line never shows at the bottom. }
procedure CalcEditRect (var r: Rect);
var
f: FontInfo;
lineHeight: integer;
begin
GetFontInfo(f);
lineHeight := f.ascent + f.descent + f.leading;
r := dispWind^.portRect;
r.left := r.left + 4;
r.right := r.right - 17; { leave room for scroll bar + 2 }
r.top := r.top + 2;
r.bottom := r.top + ((r.bottom - (r.top - 2)) div lineHeight) * lineHeight;
end;
{ Calculate the dimensions of the scroll bar rectangle for the}
{ window. Make sure that the edges overlap the window frame and}
{ the grow box.}
procedure CalcScrollRect (var r: Rect);
begin
r := dispWind^.portRect;
r.right := r.right + 1;
r.left := r.right - 16;
r.top := r.top - 1;
r.bottom := r.bottom - 14;
end;
{ Calculate the number of lines currently scrolled off}
{ the top.}
function LinesOffTop: integer;
var
ePtr: TEPtr;
begin
ePtr := dispTE^;
LinesOffTop := (ePtr^.viewRect.top - ePtr^.destRect.top) div ePtr^.lineHeight;
end;
{ Highlight the scroll bar properly. This means that it's not}
{ made active if the window itself isn't active, even if}
{ there's enough text to fill the window. }
procedure HiliteScroll;
var
result: integer;
begin
if (GetCtlMax(dispScroll) > 0) and (dispWind = FrontWindow) then
result := 0
else
result := 255;
HiliteControl(dispScroll, result);
end;
{ Scroll to the correct position. lDelta is the}
{ amount to CHANGE the current scroll setting by.}
{ Positive scrolls the text up, negative down.}
procedure ScrollText (lDelta: integer);
var
lHeight, newLine, topLine: integer;
begin
lHeight := dispTE^^.lineHeight;
topLine := LinesOffTop;
newLine := topLine + lDelta;
if newLine < 0 then
newLine := 0;
if newLine > GetCtlmax(dispScroll) then
newLine := GetCtlMax(dispScroll);
SetCtlValue(dispScroll, newLine);
TEScroll(0, (topLine - newLine) * lHeight, dispTE);
end;
{ Filter proc for tracking mousedown in scroll bar . The code}
{ for the part originally hit is stored in the control 's reference}
{ value by Mouse ( ) before calling this . }
{ Scroll by one line if the mouse is in an arrow. Scroll by a half}
{ window's worth of lines if the mouse is in a page region. }
procedure TrackScroll (theScroll: ControlHandle; partCode: integer);
var
lDelta, halfPage: integer;
begin
if partCode = GetCRefCon(theScroll) then { still in same part? }
begin
halfPage := ((dispTE^^.viewRect.bottom - dispTE^^.viewRect.top) div dispTE^^.lineHeight) div 2;
if halfPage = 0 then
halfPage := halfPage + 1;
case partCode of
inUpButton:
lDelta := -1;
inDownButton:
lDelta := 1;
inPageUp:
lDelta := -halfPage;
inPageDown:
lDelta := halfPage;
otherwise
end;
ScrollText(lDelta);
end;
end;
{ Adjust the text in the text record and the scroll bar. This is}
{ called for major catastrophes, such as resizing the window, or}
{ changing the word wrap style. It makes sure the view and}
{ destination rectangles are sized properly, and that the bottom}
{ line of text never scrolls up past the bottom line of the}
{ window, if there's enough to fill the window, and that the}
{ scroll bar max and current values are set properly.}
{ Resizing the dest rect just means resetting the right edge}
{ (the top is NOT reset), since text might be scrolled off the}
{ top (i.e., destRect.top != 0).}
procedure OverhaulDisplay;
var
r: Rect;
nLines, visLines, topLines, scrollLines, lHeight: integer;
{ number of lines in TERec }
{ number of lines displayable in window }
{ number of lines currently scrolled off top }
{ number of lines to scroll down }
begin
CalcEditRect(r);
dispTE^^.destRect.right := r.right;
dispTE^^.viewRect := r;
TECalText(dispTE); { recalc line starts }
lHeight := dispTE^^.lineHeight;
nLines := dispTE^^.nLines;
visLines := (r.bottom - r.top) div lheight;
topLines := LinesoffTop;
{ If the text doesn't fill the window (visLines > nLines - topLines),}
{ pull the text down if possible (if topLines > 0). Make sure}
{ not to try to scroll down by more lines than are hidden off the top .}
scrollLines := visLines - (nLines - topLines);
if (scrollLines > 0) and (topLines > 0) then
begin
if scrollLines > topLines then
scrollLines := topLines;
TEScroll(0, scrollLInes * lHeight, dispTE);
toplines := topLines - scrollLines;
end;
TEUpdate(r, dispTE);
if nLines - visLines < 0 then
SetCtlMax(dispScroll, 0)
else
SetCtlMax(dispScroll, nLines - VisLines);
SetCtlValue(dispScroll, topLines);
HiliteScroll;
end;
procedure callpnoarg (myProc: ProcPtr);
{ For all the Procedures that are called with no arguments }
inline
$205f, {movea.l (a7)+,a0 ; (a0) is a ptr to string, 4(a0) is mode}
$4e90;
procedure callpBoolean (myBool: Boolean; myProc: ProcPtr);
{ Two calls use Booleans as one parameter arguments. This procedure handles }
{ both of them. }
inline
$205f, {movea.l (a7)+,a0 ; (a0) is a ptr to string, 4(a0) is mode}
$4e90;
{ ---------------------------------------------------------------- }
{ Window Handler Routines }
{ ---------------------------------------------------------------- }
{ When the window comes active, highlight the scroll bar appropriately.}
{ When the window is deactivated, un-highlight the scroll bar.}
{ Redraw the grow box.}
{ Notify the host as appropriate.}
{ Note that clicking close box hides the window, which generates a}
{ deactivate event, so there is no need for a close notifier.}
procedure Activate (isActive: Boolean);
begin
SyncGlobals(nil); { sync to current port }
DrawGrowBox;
HiliteScroll;
if dActivate <> nil then
callpBoolean(isActive, dActivate);
end;
{ Update window. The update event might be in response to a}
{ window resizing. If so, move and resize the scroll bar,}
{ and recalculate the text display.}
{ The ValidRect call is done because the HideControl adds the}
{ control bounds box to the update region - which would generate}
{ another update event! Since everything is redrawn below anyway,}
{ the ValidRect is used to cancel the update.}
procedure Update (resized: Boolean);
var
r: Rect;
begin
SyncGlobals(nil); { sync to current port }
r := dispWind^.portRect;
EraseRect(r);
if resized then
begin
HideControl(dispScroll);
r := dispScroll^^.contrlRect;
ValidRect(r);
CalcScrollRect(r);
SizeControl(dispScroll, 16, r.bottom - r.top);
MoveControl(dispScroll, r.left, r.top);
OverHaulDisplay;
ShowControl(dispScroll);
end
else
begin
r := dispTE^^.viewRect;
TEUpdate(r, dispTE);
end;
DrawGrowBox;
DrawControls(dispWind); { redraw scroll bar }
end;
{ Handle mouse clicks in window}
procedure Mouse (thePt: Point; t: longint; mods: integer);
var
thePart: integer;
oldCtlValue: integer;
begin
SyncGlobals(nil); { Sync to current port }
thePart := TestControl(dispScroll, thePt);
if thePart = inThumb then
begin
OldCtlValue := GetCtlValue(dispScroll);
if TrackControl(dispScroll, thePt, nil) = inThumb then
ScrollText(GetCtlValue(dispScroll) - oldCtlValue);
end
else if thePart <> 0 then
begin
SetCRefCon(dispScroll, longint(thePart));
oldCtlValue := TrackControl(dispScroll, thePt, @TrackScroll);
end;
end;
{ Remove the display window from the list, and dispose of it.}
{ Since the clobber procedure is never called except for real display}
{ windows, and since the list must therefore be non-empty, it is}
{ not necessary to check the legality of the window or that the}
{ window's in the list.}
{ Must do SetDWindow (nil) to turn output off, if the window being}
{ clobbered is the current output window.}
procedure Clobber;
var
{$IFC not singleDisplay}
h, h2: DIHandle;
{$ENDC}
keepgoing: Boolean;
begin
SyncGlobals(nil); { sync to current port }
if dispWind = curDispWind then { is it the first window in list? }
SetDWindow(nil);
{$IFC not singleDisplay}
if dwList^^.dWind = dispWind then { found it }
begin
h2 := dwList;
dwList := dwList^^.dNext;
end
else
begin
h := dwList;
keepgoing := true;
while (h <> nil) and keepgoing do
begin
h2 := h^^.dNext;
if h2^^.dWind = dispWind then
begin
h^^.dNext := h2^^.dNext;
keepgoing := false;
end;
h := h2;
end;
end;
DisposHandle(Handle(h2)); { get rid of information structure }
{$ENDC}
TEDispose(dispTE); { toss text record }
DisposeWindow(dispWind); { toss window and scroll bar }
dispWind := nil;
end;
{ ---------------------------------------------------------------- }
{ Control Routines }
{ ---------------------------------------------------------------- }
{ Test whether a window is a legal display window or not }
function IsDWindow;
begin
{$IFC singleDisplay}
IsDWindow := (theWind = dispWind) and (dispWind <> nil);
{$ELSEC}
IsDWindow := GetDInfo(theWind) <> nil;
{$ENDC}
end;
{ Return handle to display window's text record}
function GetDWindowTE;
{$IFC not singleDisplay}
var
dInfo: DIHandle;
{$ENDC}
begin
{$IFC not singleDisplay}
{Fix by Ingemar -94: The following line was missing in the 2.0 release:}
dInfo := GetDInfo(theWind);
if dInfo = nil then {GetDInfo(theWind)}
GetDWindowTE := nil
else
GetDWIndowTE := dInfo^^.dTE;
{$ELSEC}
if ISDWindow(theWind) then
GetDWindowTE := dispTE
else
GetDWindowTE := nil;
{$ENDC}
end;
{ Change the text display characteristics of a display window}
{ and redisplay it. As a side effect, this always scrolls to the}
{ home position.}
procedure SetDWindowStyle;
var
savePort: GrafPtr;
f: FontInfo;
te: TEHandle;
r: Rect;
begin
if theWind = nil then { reset window creation defaults }
begin
d_font := font;
d_size := size;
d_wrap := wrap;
d_just := just;
end
else
begin
if IsDWindow(theWind) then
begin
GetPort(savePort);
SyncGlobals(theWind);
SetPort(dispWind);
te := dispTE;
r := te^^.viewRect;
EraseRect(r);
r := te^^.destRect; { scroll home without redrawing }
OffsetRect(r, 0, 2 - r.top);
te^^.destRect := r;
te^^.crOnly := wrap; { set word wrap }
TESetJust(just, te); { set justification }
TextFont(font); { set the font and point size }
TextSize(size); { of text record (this is the }
GetFontInfo(f); { hard part) }
te^^.lineHeight := f.ascent + f.descent + f.leading;
te^^.fontAscent := f.ascent;
te^^.txFont := font;
te^^.txSize := size;
OverhaulDisplay;
SetPort(savePort);
end;
end;
end;
{ Scroll the text in the window so that line lineNum is at the top.}
{ First line is line zero.}
procedure SetDWindowPos;
var
savePort: GrafPtr;
begin
if IsDWindow(theWind) then
begin
GetPort(savePort);
SyncGlobals(theWind);
SetPort(dispWind);
ScrollText(lineNum - GetCtlValue(dispScroll));
SetPort(savePort);
end;
end;
{ Set display window activate notification procedure.}
{ Pass nil to disable it.}
procedure SetDWindowNotify;
{$IFC not singleDisplay}
var
dInfo: DIHAndle;
{$ENDC}
begin
if theWind = nil then { reset window creation default }
d_activate := p
else
begin
{$IFC singleDisplay}
if (ISDWindow(theWind)) then
dActivate := p;
{$ELSEC}
dInfo := GetDInfo(theWind);
if dInfo <> nil then
dInfo^^.dActivate := p;
{$ENDC}
end;
end;
{ Set display window autoflush characteristics}
procedure SetDWindowFlush;
{$IFC not singleDisplay}
var
dInfo: DIHandle;
{$ENDC}
begin
if maxText > longint(32767) then
maxText := 32767;
if maxText < d_loMaxText then
maxText := d_loMaxText;
if flushAmt < d_loFlushAmt then
flushAmt := d_loFlushAmt;
if theWind = nil then
begin { reset window creation defaults }
d_maxText := maxText;
d_flushAmt := flushAmt;
end
else
begin
{$IFC singleDisplay}
if (IsDWindow(theWind)) then
begin
dMaxText := maxText;
dFlushAmt := flushAmt;
end;
{$ELSEC}
dInfo := GetDInfo(theWind);
if dInfo <> nil then
begin
dInfo^^.dMaxText := maxText;
dInfo^^.dFlushAmt := flushAmt;
end;
{$ENDC}
end;
end;
{ Set which display window is to be used for output. If theWind}
{ is nil, output is turned off. If theWind is not a legal display}
{ window, nothing is done.}
procedure SetDWindow;
begin
if (theWind = nil) or IsDWindow(theWind) then
curDispWind := theWind;
end;
{ Get the WindowPtr of the current output display window. If}
{ output is turned off, this will be nil.}
procedure GetDWindow;
begin
theWind := curDispWind;
end;
{ Flush text from the window and readjust the display.}
procedure FlushDWindow;
begin
if IsDWindow(theWind) then
begin
SyncGlobals(theWind);
TESetSelect(longint(0), byteCount, dispTE); { select text }
TEDelete(dispTE); { clobber it }
OverhaulDisplay;
end;
end;
{ Create and initialize a display window and the associated data}
{ structures, and return the window pointer. Install window in}
{ list of display windows.}
procedure SetupDWindow;
var
r: Rect;
savePort: GrafPtr;
{$IFC not singleDisplay}
dInfo: DIHandle;
{$ENDC}
dummy: Boolean;
begin
dummy := SkelWindow(dispWind, @Mouse, nil, @Update, @Activate, nil, @Clobber, nil, false);
{ the window }
{ mouse click handler }
{ key clicks are ignored }
{ window updating procedure }
{ window activate/deactivate procedure }
{ TransSkel hides window if no close proc }
{ (generates deactivate event) }
{ window disposal procedure }
{ no idle proc }
{ irrelevant since no idle proc }
{ Build the scroll bar. Make sure the borders overlap the}
{ window frame and the frame of the grow box.}
CalcScrollRect(r);
dispScroll := NewControl(dispWind, r, '', true, 0, 0, 0, scrollBarProc, longint(0));
{ Create the TE record used for text display. Use defaults for}
{ display characteristics. Setting window style overhauls}
{ display, so can cancel and update event pending for the window.}
CalcEditRect(r);
dispTE := TENew(r, r);
{$IFC not singleDisplay}
{ Get new information structure, attach to list of known display}
{ windows.}
dInfo := DIHandle(NewHandle(sizeof(DisplayInfo)));
dInfo^^.dNext := dwList;
dwList := dInfo;
dInfo^^.dWind := dispWind;
dInfo^^.dScroll := dispScroll;
dInfo^^.dTE := dispTE;
{$ENDC}
SetDWindowNotify(dispWind, d_activate);
SetDWindowFlush(dispWind, d_maxtext, d_flushAmt);
SetDWindowStyle(dispWind, d_font, d_size, d_wrap, d_just);
{ Make window current display output window}
SetDWindow(dispWind);
end;
{ Create and initialize a display window and the associated data}
{ structures, and return the window pointer. Install window in}
{ list of display windows. In single-window mode, disallow}
{ creation of a new window if one already exists.}
{ The parameters are similar to those for NewWindow. See Inside}
{ Macintosh.}
function NewDWindow;
begin
{$IFC singleDisplay}
if dispWind <> nil then
NewDWindow := nil
else
{$ENDC}
begin
dispWind := NewWindow(nil, bounds, title, visible, documentProc, behind, goAway, refCon);
SetUpDWindow;
NewDWindow := dispWind;
end;
end;
{ Create and initialize a display window (using a resource) and}
{ the associated data structures, and return the window pointer.}
{ Install window in list of display windows. In single-window}
{ mode, disallow creation of a new window if one already exists.}
{ The parameters are similar to those for GetNewWindow. See Inside}
{ Macintosh.}
function GetNewDWindow;
begin
{$IFC singleDisplay}
if dispWind <> nil then
GetNewDWindow := nil
else
{$ENDC}
begin
dispWind := GetNewWindow(resourceNum, nil, behind);
SetUPDWindow;
GetNewDWindow := dispWind;
end;
end;
{ ------------------------------------------------------------ }
{ Output Routines }
{ ------------------------------------------------------------ }
{}
{ Write text to display area if output is on (curDispWind != nil).}
{ DisplayText is the fundamental output routine. All other}
{ output calls map (eventually) to it.}
{ First check whether the insertion will cause overflow and flush}
{ out some stuff if so. Insert new text at the end, then test}
{ whether lines must be scrolled to get the new stuff to show up.}
{ If yes, then do the scroll. Set values of scroll bar properly}
{ and highlight as appropriate.}
{ The current port is preserved. Since all output calls end up}
{ here, it's the only output routine that has to save the port}
{ and check whether output is on.}
procedure DisplayText;
var
nLines, dispLines, topLines, scrollLines, lHeight: integer;
{ number of lines in TERec }
{ number of lines displayable in window }
{ number of lines currently scrolled off top }
{ number of lines to scroll up }
r: Rect;
savePort: GrafPtr;
dTE: TEHandle;
begin
if curDispWind <> nil then
begin
GetPort(savePort);
SetPort(curDispWind);
SyncGlobals(curDispWind);
dTE := dispTE;
if dTE^^.teLength + len > dMaxText then { check overflow }
begin
FlushDWindow(dispWind, dFlushAmt);
DisplayString('(autoflush occurred)');
end;
lHeight := dTE^^.lineHeight;
TESetSelect(longint(32767), longint(32767), dTE);
TEInsert(theText, len, dTE);
r := dTE^^.viewRect;
nLines := dTE^^.nLines;
dispLines := (r.bottom - r.top) div lHeight;
topLines := LinesOffTop;
scrollLines := nLines - (topLines + dispLines);
if scrollLines > 0 then { must scroll up }
TEScroll(0, -lHeight * scrollLines, dTE); { scroll up }
topLines := nLines - dispLines;
if (topLines >= 0) and (GetCtlMax(dispScroll) <> topLines) then
begin
SetCtlMax(dispScroll, topLines);
SetCtlValue(dispScroll, topLines);
end;
HiliteScroll;
SetPort(savePort);
end;
end;
{ Derived output routines:}
{ DisplayString Write (Pascal) string}
{ DisplayLong Write value of long integer}
{ DisplayInt Write value of integer}
{ DisplayChar Write character}
{ DisplayHexLong Write value of long integer in hex (8 digits)}
{ DisplayHexInt Write value of integer in hex (4 digits)}
{ DisplayHexChar Write value of character in hex (2 digit)}
{ DisplayBoolean Write boolean value}
{ DisplayLn Write carriage return}
procedure DisplayString;
var
myPtr: Ptr;
begin
myPtr := Ptr(longint(@theStr) + 1);
DisplayText(myPtr, longint(length(theSTr)));
end;
procedure DisplayLong;
var
s: Str255;
begin
NumToString(l, s);
DisplayString(s);
end;
procedure DisplayInt;
begin
DisplayLong(longint(i));
end;
procedure DisplayChar;
var
myPtr: Ptr;
begin
myPtr := @c;
myPtr := Ptr(longint(myPtr) + 1);
DisplayText(myPtr, longint(1));
end;
procedure DisplayLn;
begin
DisplayChar(char(13));
end;
procedure DisplayBoolean;
begin
if b then
DisplayString('True')
else
DisplayString('False');
end;
procedure HexByte (value: integer); {value should be 0..15}
begin
if value < 10 then
DisplayChar(char(value + integer('0')))
else
DisplayChar(char(value + (integer('a') - 10)));
end;
procedure DisplayHexChar;
begin
HexByte(integer(BitAnd(BitShift(longint(c), -4), $0000000f)));
HexByte(integer(BitAnd(longint(c), $0000000f)));
end;
procedure DisplayHexInt;
begin
DisplayHexChar(char(BitAnd(BitShift(longint(i), -8), $000000ff)));
DisplayHexChar(char(BitAnd(longint(i), $000000ff)));
end;
procedure DisplayHexLong;
begin
DisplayHexInt(Integer(BitAnd(BitShift(l, -16), $0000ffff)));
DisplayHexInt(integer(LoWord(l)));
end;
procedure TransDisplayInit;
begin
{ Default values for display window characteristics}
d_font := monaco; { default font }
d_size := 9; { default pointsize }
d_wrap := 0; { default word wrap (on) }
d_just := teJustLeft; { default justification }
d_maxText := 30000; { default max text allowed }
d_flushAmt := 25000; { default autoflush amount }
d_activate := nil; { default notification proc }
{ Lowest allowable values for autoflush characteristics}
d_loMaxText := 100;
d_loFlushAmt := 100;
{ dwList points to a list of structures describing the known display}
{ windows.}
{ curDispWind is the current output window.}
{ If curDispWind = nil, output is currently turned off.}
{$IFC not singleDisplay}
dwList := nil;
{$ENDC}
dispWind := nil;
curDispWind := nil;
end;
end.